import com.idol.web.container.ServletContainer;
import com.idol.web.servlet.http.HttpServlet;
import com.idol.web.util.Const;
import loader.MyClassLoader;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import processor.RequestProcessor;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.List;
import java.util.concurrent.*;

/**
 * @author Supreme_Sir
 * @version 1.0
 * @className Bootstrap
 * @description
 * @date 2020/11/22 20:35
 **/
public class Bootstrap {
    private ThreadPoolExecutor threadPoolExecutor;
    private ServletContainer servletContainer;
    private static final Integer PORT = 8080;
    private MyClassLoader classLoader;

    public static void main(String[] args) throws IOException {
        Bootstrap bootstrap = new Bootstrap();
        bootstrap.initServlet();
        bootstrap.start();
    }

    public void start() throws IOException {
        ServerSocket serverSocket = new ServerSocket(PORT);
        do {
            Socket socket = serverSocket.accept();
            RequestProcessor processor = new RequestProcessor(socket, servletContainer);
            threadPoolExecutor.execute(processor);
        } while (true);
    }

    private void initServlet() {
        String miniCatAbsoulteRootPath = Bootstrap.class.getResource("/").getPath();
        File rootDir = new File(miniCatAbsoulteRootPath);
        // 找到 webapps 文件夹
        File[] listFiles = rootDir.listFiles(new FileFilter() {
            @Override
            public boolean accept(File pathname) {
                return Const.WEBAPPS_DIR.getVal().equals(pathname.getName());
            }
        });
        // 拿到 webapps 下的所有项目
        if (listFiles.length == 0) {
            return;
        } else {
            listFiles = listFiles[0].listFiles(new FileFilter() {
                @Override
                public boolean accept(File pathname) {
                    return pathname.isDirectory();
                }
            });
        }
        try {
            for (File file : listFiles) {
                if (!file.isDirectory()) {
                    continue;
                }

                String webXml = miniCatAbsoulteRootPath + Const.WEBAPPS_DIR.getVal() + File.separator + file.getName() + File.separator + "web.xml";
                File xmlFile = new File(webXml);
                if (!xmlFile.exists()) {
                    continue;
                }
                InputStream inputStream = new FileInputStream(xmlFile);

                SAXReader saxReader = new SAXReader();
                Document document = saxReader.read(inputStream);
                Element root = document.getRootElement();
                List<Element> selectNodes = root.selectNodes("//servlet");
                for (Element node : selectNodes) {
                    Element servletNameElement = (Element) node.selectSingleNode("//servlet-name");
                    String servletName = servletNameElement.getStringValue();

                    Element servletClassElement = (Element) node.selectSingleNode("//servlet-class");
                    String servletClass = servletClassElement.getStringValue();

                    Element servletMapping = (Element) root.selectSingleNode("/web-app/servlet-mapping[servlet-name='" + servletName + "']");
                    String urlPattern = servletMapping.selectSingleNode("url-pattern").getStringValue();
                    HttpServlet httpServlet = (HttpServlet) classLoader.findClass(file.getName() + "." + servletClass).newInstance();
                    servletContainer.put(file.getName(), urlPattern.substring(1), httpServlet);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public Bootstrap() {
        // 定义一个线程池
        // 线程池中常驻线程数
        int corePoolSize = 10;
        // 最大线程数
        int maximumPoolSize =50;
        // 线程存活时间
        long keepAliveTime = 100L;
        // 线程存活时间单位
        TimeUnit unit = TimeUnit.SECONDS;
        // 线程队列
        BlockingQueue<Runnable> workQueue = new ArrayBlockingQueue<>(50);
        // 线程工厂
        ThreadFactory threadFactory = Executors.defaultThreadFactory();
        // 拒绝策略
        RejectedExecutionHandler handler = new ThreadPoolExecutor.AbortPolicy();
        threadPoolExecutor = new ThreadPoolExecutor(corePoolSize, maximumPoolSize,
                keepAliveTime, unit, workQueue, threadFactory, handler);

        servletContainer = ServletContainer.getInstance();

        classLoader = new MyClassLoader();
    }
}
